package com.sqlcheck.service.impl;

import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.sqlcheck.dto.git.GitProjectInfo;
import com.sqlcheck.dto.git.GitRepositoryInfo;
import com.sqlcheck.enums.GitPlatform;
import com.sqlcheck.service.GitApiService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;

import org.springframework.http.ResponseEntity;
import org.springframework.stereotype.Service;
import org.springframework.web.client.RestTemplate;

import java.util.ArrayList;
import java.util.List;
import java.util.regex.Matcher;
import java.util.regex.Pattern;

@Slf4j
@Service("giteeApiService")
@RequiredArgsConstructor
public class GiteeApiServiceImpl implements GitApiService {

    private final RestTemplate restTemplate;
    private final ObjectMapper objectMapper;

    // Gitee项目URL的正则表达式
    private static final Pattern PROJECT_URL_PATTERN = Pattern.compile(
            "https?://gitee\\.com/([^/]+/[^/]+)(?:\\.git)?/?$");

    // Gitee API基础URL
    private static final String GITEE_API_BASE = "https://gitee.com/api/v5";

    @Override
    public GitPlatform getSupportedPlatform() {
        return GitPlatform.GITEE;
    }

    @Override
    public List<GitProjectInfo> getUserProjects(String accessToken, int page, int perPage) {
        try {
            String apiUrl = String.format("%s/user/repos?access_token=%s&page=%d&per_page=%d&sort=updated&order=desc",
                    GITEE_API_BASE, accessToken, page, perPage);

            ResponseEntity<String> response = restTemplate.getForEntity(apiUrl, String.class);

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                JsonNode jsonArray = objectMapper.readTree(response.getBody());
                List<GitProjectInfo> projects = new ArrayList<>();

                for (JsonNode projectNode : jsonArray) {
                    projects.add(parseProjectInfo(projectNode));
                }

                return projects;
            }

            log.error("获取Gitee用户项目列表失败: {}", response.getStatusCode());
            return new ArrayList<>();

        } catch (Exception e) {
            log.error("获取Gitee用户项目列表异常: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public GitProjectInfo getProjectByUrl(String accessToken, String projectUrl) {
        try {
            // 解析项目URL获取owner/repo
            String ownerRepo = extractProjectIdentifier(projectUrl);
            if (ownerRepo == null) {
                log.error("无效的Gitee项目URL: {}", projectUrl);
                return null;
            }

            String apiUrl = String.format("%s/repos/%s?access_token=%s", GITEE_API_BASE, ownerRepo, accessToken);
            log.info("获取Gitee项目信息: URL: {}", apiUrl);
            ResponseEntity<String> response = restTemplate.getForEntity(apiUrl, String.class);

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                JsonNode projectNode = objectMapper.readTree(response.getBody());
                return parseProjectInfo(projectNode);
            }

            log.error("获取Gitee项目信息失败: {} - {}", response.getStatusCode(), response.getBody());
            return null;

        } catch (Exception e) {
            log.error("获取Gitee项目信息异常: {}", e.getMessage(), e);
            return null;
        }
    }

    @Override
    public GitRepositoryInfo getRepositoryInfo(String accessToken, String projectId) {
        try {
            String apiUrl = String.format("%s/repos/%s?access_token=%s", GITEE_API_BASE, projectId, accessToken);

            ResponseEntity<String> response = restTemplate.getForEntity(apiUrl, String.class);

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                JsonNode repoNode = objectMapper.readTree(response.getBody());

                // 获取最后一次提交信息
                JsonNode lastCommit = getLastCommit(accessToken, projectId);

                return GitRepositoryInfo.builder()
                        .id(repoNode.has("id") ? repoNode.get("id").asLong() : null)
                        .name(repoNode.has("name") ? repoNode.get("name").asText() : null)
                        .path(repoNode.has("path") ? repoNode.get("path").asText() : null)
                        .fullPath(repoNode.has("full_name") ? repoNode.get("full_name").asText() : null)
                        .description(repoNode.has("description") && !repoNode.get("description").isNull() ? repoNode.get("description").asText() : null)
                        .webUrl(repoNode.has("html_url") ? repoNode.get("html_url").asText() : null)
                        .cloneUrl(repoNode.has("clone_url") ? repoNode.get("clone_url").asText() : null)
                        .visibility(repoNode.has("private") ? (repoNode.get("private").asBoolean() ? "private" : "public") : "public")
                        .archived(false)
                        .createdAt(repoNode.has("created_at") ? repoNode.get("created_at").asText() : null)
                        .lastActivityAt(repoNode.has("updated_at") ? repoNode.get("updated_at").asText() : null)
                        .defaultBranch(
                                repoNode.has("default_branch") ? repoNode.get("default_branch").asText() : "master")
                        .emptyRepo(repoNode.has("empty") ? repoNode.get("empty").asBoolean() : false)
                        .lastCommitId(
                                lastCommit != null && lastCommit.has("sha") ? lastCommit.get("sha").asText() : null)
                        .lastCommitMessage(lastCommit != null && lastCommit.has("commit")
                                && lastCommit.get("commit").has("message")
                                        ? lastCommit.get("commit").get("message").asText()
                                        : null)
                        .lastCommitAuthor(lastCommit != null && lastCommit.has("commit")
                                && lastCommit.get("commit").has("author") &&
                                lastCommit.get("commit").get("author").has("name")
                                        ? lastCommit.get("commit").get("author").get("name").asText()
                                        : null)
                        .lastCommitDate(lastCommit != null && lastCommit.has("commit")
                                && lastCommit.get("commit").has("author") &&
                                lastCommit.get("commit").get("author").has("date")
                                        ? lastCommit.get("commit").get("author").get("date").asText()
                                        : null)
                        .build();
            }

            log.error("获取Gitee仓库信息失败: {}", response.getStatusCode());
            return null;

        } catch (Exception e) {
            log.error("获取Gitee仓库信息异常: {}", e.getMessage(), e);
            return null;
        }
    }

    @Override
    public boolean validateProjectAccess(String accessToken, String projectUrl) {
        if (accessToken == null || accessToken.trim().isEmpty()) {
            log.warn("Gitee访问令牌为空");
            return false;
        }
        if (projectUrl == null || projectUrl.trim().isEmpty()) {
            log.warn("Gitee项目URL为空");
            return false;
        }

        try {
            log.info("验证Gitee项目访问权限: Token: {}, URL: {}", accessToken, projectUrl);
            GitProjectInfo projectInfo = getProjectByUrl(accessToken, projectUrl);
            return projectInfo != null;
        } catch (Exception e) {
            log.error("验证Gitee项目访问权限异常: {}, URL: {}", e.getMessage(), projectUrl);
            return false;
        }
    }

    @Override
    public String getDefaultBranch(String accessToken, String projectId) {
        try {
            String apiUrl = String.format("%s/repos/%s?access_token=%s", GITEE_API_BASE, projectId, accessToken);

            ResponseEntity<String> response = restTemplate.getForEntity(apiUrl, String.class);

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                JsonNode projectNode = objectMapper.readTree(response.getBody());
                return projectNode.has("default_branch") ? projectNode.get("default_branch").asText() : "master";
            }

            return "master";

        } catch (Exception e) {
            log.error("获取Gitee默认分支异常: {}", e.getMessage(), e);
            return "master";
        }
    }

    @Override
    public List<String> getProjectBranches(String accessToken, String projectId) {
        try {
            String apiUrl = String.format("%s/repos/%s/branches?access_token=%s", GITEE_API_BASE, projectId,
                    accessToken);

            ResponseEntity<String> response = restTemplate.getForEntity(apiUrl, String.class);

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                JsonNode branchesArray = objectMapper.readTree(response.getBody());
                List<String> branches = new ArrayList<>();

                for (JsonNode branchNode : branchesArray) {
                    if (branchNode.has("name")) {
                        branches.add(branchNode.get("name").asText());
                    }
                }

                return branches;
            }

            log.error("获取Gitee项目分支列表失败: {}", response.getStatusCode());
            return new ArrayList<>();

        } catch (Exception e) {
            log.error("获取Gitee项目分支列表异常: {}", e.getMessage(), e);
            return new ArrayList<>();
        }
    }

    @Override
    public String extractProjectIdentifier(String projectUrl) {
        if (projectUrl == null || projectUrl.trim().isEmpty()) {
            log.warn("Gitee项目URL为空或null");
            return null;
        }

        try {
            Matcher matcher = PROJECT_URL_PATTERN.matcher(projectUrl.trim());
            if (matcher.matches()) {
                return matcher.group(1);
            }
            log.warn("Gitee项目URL格式不匹配: {}", projectUrl);
            return null;
        } catch (Exception e) {
            log.error("解析Gitee项目URL异常: {}, URL: {}", e.getMessage(), projectUrl);
            return null;
        }
    }

    @Override
    public String buildCloneUrl(String projectUrl, String accessToken) {
        try {
            if (projectUrl == null || projectUrl.trim().isEmpty()) {
                return null;
            }

            // 确保URL不以.git结尾
            String cleanUrl = projectUrl.replaceAll("\\.git$", "");

            // Gitee支持使用access_token参数或者在URL中嵌入token
            if (cleanUrl.startsWith("https://")) {
                return cleanUrl.replace("https://", "https://" + accessToken + "@") + ".git";
            } else if (cleanUrl.startsWith("http://")) {
                return cleanUrl.replace("http://", "http://" + accessToken + "@") + ".git";
            }

            return cleanUrl + ".git";

        } catch (Exception e) {
            log.error("构建Gitee克隆URL失败: {}", e.getMessage(), e);
            return projectUrl;
        }
    }

    private JsonNode getLastCommit(String accessToken, String projectId) {
        try {
            String apiUrl = String.format("%s/repos/%s/commits?access_token=%s&per_page=1", GITEE_API_BASE, projectId,
                    accessToken);

            ResponseEntity<String> response = restTemplate.getForEntity(apiUrl, String.class);

            if (response.getStatusCode().is2xxSuccessful() && response.getBody() != null) {
                JsonNode commitsArray = objectMapper.readTree(response.getBody());
                if (commitsArray.isArray() && commitsArray.size() > 0) {
                    return commitsArray.get(0);
                }
            }

            return null;

        } catch (Exception e) {
            log.error("获取Gitee最后提交信息异常: {}", e.getMessage(), e);
            return null;
        }
    }

    private GitProjectInfo parseProjectInfo(JsonNode projectNode) {
        return GitProjectInfo.builder()
                .id(projectNode.has("id") ? projectNode.get("id").asLong() : null)
                .name(projectNode.has("name") ? projectNode.get("name").asText() : null)
                .path(projectNode.has("path") ? projectNode.get("path").asText() : null)
                .fullPath(projectNode.has("full_name") ? projectNode.get("full_name").asText() : null)
                .description(projectNode.has("description") && !projectNode.get("description").isNull()
                        ? projectNode.get("description").asText()
                        : null)
                .webUrl(projectNode.has("html_url") ? projectNode.get("html_url").asText() : null)
                .defaultBranch(
                        projectNode.has("default_branch") ? projectNode.get("default_branch").asText() : "master")
                .archived(false)
                .visibility(projectNode.has("private") ? (projectNode.get("private").asBoolean() ? "private" : "public")
                        : "public")
                .createdAt(projectNode.has("created_at") ? projectNode.get("created_at").asText() : null)
                .lastActivityAt(projectNode.has("updated_at") ? projectNode.get("updated_at").asText() : null)
                .build();
    }
}